﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using ApartmentBillsManager.Start.Annotations;
using ApartmentBillsManager.Start.Common;
using ApartmentBillsManager.Start.Manager;

namespace ApartmentBillsManager.Start.Services
{
    class CreateEditApartment : INotifyPropertyChanged
    {
        #region Data Members
        private string _apartmentName;
        private ObservableCollection<Bill> _openBills;
        private ObservableCollection<Bill> _closedBills;
        private List<BalanceRow> _balance;
        private MessageBoxResult _messageBoxResult;
        private const string EditingErrorMessage = "Roommates list cannot be changed because there are open bills.";
        private const string EditingErrorMessageCaption = "Open Bills Conflict";
        #endregion

        #region Properties
        public string ApartmentName
        {
            get { return _apartmentName; }
            set
            {
                _apartmentName = value;
                OnPropertyChanged("ApartmentName");
                OnPropertyChanged("CanCreateApartment");
            }
        }

        public ObservableCollection<Roommate> Roommates { get; set; }

        public bool CanCreateApartment
        {
            get
            {
                if (string.IsNullOrWhiteSpace(ApartmentName))
                    return false;

                if (Roommates.Count == 0)
                    return false;

                return true;
            }
        }
        #endregion

        #region Public Methods
        public Apartment CreateNewApartment()
        {
            Roommates = new ObservableCollection<Roommate>();
            ApartmentName = "My Apartment";

            _openBills = new ObservableCollection<Bill>();
            _closedBills = new ObservableCollection<Bill>();
            _balance = new List<BalanceRow>();

            OpenWindow();

            return _messageBoxResult == MessageBoxResult.OK ? new Apartment(ApartmentName, Roommates, _openBills, _closedBills, _balance) : null;
        }

        public Apartment EditExistingApartment(Apartment apartment)
        {
            Roommates = new ObservableCollection<Roommate>(apartment.Roommates);
            ApartmentName = apartment.AptName;

            _openBills = apartment.OpenBills;
            _closedBills = apartment.ClosedBills;
            _balance = apartment.Balance;

            OpenWindow();

            return _messageBoxResult == MessageBoxResult.OK ? new Apartment(ApartmentName, Roommates, _openBills, _closedBills, _balance) : null;
        }

        public void CreateNewRoommate(object parameter)
        {
            if (_openBills.Count == 0)
            {
                var newRoommate = ObjectsFactory.CreateNewRoommate();

                if (newRoommate != null)
                    Roommates.Add(newRoommate);

                OnPropertyChanged("CanCreateApartment");
            }
            else
            {
                MessageBox.Show(EditingErrorMessage, EditingErrorMessageCaption);
            }
        }

        public void EditExistingRoommate(object roommate)
        {
            if (_openBills.Count == 0)
            {
                var editedRoommate = ObjectsFactory.EditExistingRoomate(roommate as Roommate);

                if (editedRoommate != null)
                {
                    Roommates.Remove(roommate as Roommate);
                    Roommates.Add(editedRoommate);
                }

                OnPropertyChanged("CanCreateApartment");
            }
            else
            {
                MessageBox.Show(EditingErrorMessage, EditingErrorMessageCaption);
            }
        }

        public void RemoveExistingRoommate(object roommate)
        {
            if (_openBills.Count == 0)
            {
                Roommates.Remove(roommate as Roommate);
                OnPropertyChanged("CanCreateApartment");
            }
            else
            {
                MessageBox.Show(EditingErrorMessage, EditingErrorMessageCaption);
            }
        }
        #endregion

        #region Private Methods
        private void OpenWindow()
        {
            var createNewApartmentWindow = new Window
                {
                    Content = this,
                    Title = "Create New Apartment",
                    SizeToContent = SizeToContent.WidthAndHeight
                };

            createNewApartmentWindow.ShowDialog();
        }

        private void CreateApartmentButton(object obj)
        {
            _messageBoxResult = MessageBoxResult.OK;

            CloseWindow();
        }

        private void CanceApartmentButton(object obj)
        {
            _messageBoxResult = MessageBoxResult.Cancel;

            CloseWindow();
        }

        private void CloseWindow()
        {
            Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive).Close();
        }
        #endregion

        #region Commands
        public ICommand CreateNewRoommateCommand
        {
            get { return new DelegateCommand(CreateNewRoommate); }
        }

        public ICommand EditExistingRoommateCommand
        {
            get { return new DelegateCommand(EditExistingRoommate); }
        }

        public ICommand RemoveExistingRoommateCommand
        {
            get { return new DelegateCommand(RemoveExistingRoommate); }
        }

        public ICommand CreateApartmentButtonCommand
        {
            get { return new DelegateCommand(CreateApartmentButton); }
        }

        public ICommand CancelApartmentButtonCommand
        {
            get { return new DelegateCommand(CanceApartmentButton); }
        }
        #endregion


        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
